﻿
namespace Patterns4Net.Tests.PatternEnforcer.Core
{
    using System.Diagnostics.Contracts;
    using Mono.Cecil;
    using NUnit.Framework;
    using Patterns4Net.PatternEnforcer.Core;

    [TestFixture]
    [ContractVerification(false)] // Moq (mocking library for .NET) has no contracts definition which would cause lot of work here...
    public class CompositeCheckerTest
    {
        [Test]
        public void Check_Calls_All_Given_Checkers()
        {
            var checker1 = new Moq.Mock<IChecker<TypeReference>>();
            checker1.Setup(x => x.Check(Moq.It.IsAny<TypeReference>()))
                .Returns(CheckerResult.CreateSimpleResult(true, new CheckerError("message")))
                .Verifiable();

            var checker2 = new Moq.Mock<IChecker<TypeReference>>();
            checker2.Setup(x => x.Check(Moq.It.IsAny<TypeReference>()))
                .Returns(CheckerResult.CreateSimpleResult(true, new CheckerError("message")))
                .Verifiable();

            var composite = new CompositeChecker<TypeReference>(new[] { checker1.Object, checker2.Object });
            composite.Check(new TypeReference("Hello.World", "Type", null, null));

            checker1.Verify();
            checker2.Verify();
        }

        [TestCase(false)]
        [TestCase(true)]
        public void Check_Returns_Correct_Result_When_The_Only_Given_Component_Returns(bool componentResult)
        {
            var checker1 = new Moq.Mock<IChecker<TypeReference>>();
            checker1.Setup(x => x.Check(Moq.It.IsAny<TypeReference>()))
                .Returns(CheckerResult.CreateSimpleResult(componentResult, new CheckerError("message")));

            var composite = new CompositeChecker<TypeReference>(new[] { checker1.Object });
            var result = composite.Check(new TypeReference("Hello.World", "Type", null, null));

            Assert.AreEqual(componentResult, result.IsValid);
        }

        [Test]
        public void Check_Passes_Correct_Parameter_To_Components()
        {
            var subject = new TypeReference("Hello", "World", null, null);
            var checker1 = new Moq.Mock<IChecker<TypeReference>>();
            checker1.Setup(x => x.Check(Moq.It.Is<TypeReference>(t => t == subject)))
                .Returns(CheckerResult.CreateSimpleResult(true, new CheckerError("message")))
                .Verifiable();

            var composite = new CompositeChecker<TypeReference>(new[] { checker1.Object });
            composite.Check(subject);

            checker1.Verify();
        }
    }
}
